package com.xwaiy.xwaiyrpc.server.tcp;

import com.xwaiy.xwaiyrpc.exception.RpcException;
import com.xwaiy.xwaiyrpc.exception.enums.ErrorCode;
import com.xwaiy.xwaiyrpc.model.RpcRequest;
import com.xwaiy.xwaiyrpc.model.RpcResponse;
import com.xwaiy.xwaiyrpc.protocol.Decoder;
import com.xwaiy.xwaiyrpc.protocol.Encoder;
import com.xwaiy.xwaiyrpc.protocol.ProtocolMessage;
import com.xwaiy.xwaiyrpc.protocol.TypeEnum;
import com.xwaiy.xwaiyrpc.registry.LocalRegistry;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetSocket;

import java.io.IOException;
import java.lang.reflect.Method;


/**
 * TCP请求处理器
 * @Author Xwaiy
 * @Date 2025/8/29 15:15
 **/
public class TcpServiceHandler implements Handler<NetSocket> {
    @Override
    public void handle(NetSocket netSocket) {
        TcpBufferHandler handler = new TcpBufferHandler(buffer -> {
            ProtocolMessage<RpcRequest> msg;
            try{
                msg = (ProtocolMessage<RpcRequest>) Decoder.decode(buffer);
            }catch (IOException e) {
                throw new RpcException(ErrorCode.PROTOCOL_DECODE_FAILED, "协议消息解码错误", e);
            }

            RpcRequest req = msg.getBody();

            RpcResponse resp = new RpcResponse();
            try{
                Object serviceImpl = LocalRegistry.getService(req.getServiceName());
                Method method = serviceImpl.getClass().getMethod(req.getMethodName(), req.getParamTypes());
                Object result = method.invoke(serviceImpl, req.getParams());

                resp.setData(result);
                resp.setDataType(method.getReturnType());
                resp.setMsg("OK");
            }catch (Exception e) {
                e.printStackTrace();
                resp.setMsg(e.getMessage());
                resp.setException(e);
            }

            // 发送
            ProtocolMessage.Header header = msg.getHeader();
            header.setType((byte) TypeEnum.RESPONSE.getKey());
            ProtocolMessage<RpcResponse> respMsg = new ProtocolMessage<>(header, resp);
            try{
                Buffer encode = Encoder.encode(respMsg);
                netSocket.write(encode);
            }catch (IOException e) {
                throw new RpcException(ErrorCode.PROTOCOL_ENCODE_FAILED, "协议消息编码错误", e);
            }
        });
        netSocket.handler(handler);
    }
}
